﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using RadowCore.Models;
using System.Threading;
using RadowCore.Helpers;
using RadowCore.Algo;
using Microsoft.Glee.Drawing;

namespace RadowCore
{   
    public partial class Form1 : Form
    {
        SplashWindow swin;
        /// <summary>
        /// a hash table contains all the propagation graphs, key is pg hash key, value is pgnode (root node in the pg)
        /// </summary>
        Dictionary<String, PGNode> PGRepository;
        public Form1()
        {
            this.PGRepository = new Dictionary<string, PGNode>();
            //Thread t = new Thread(new ThreadStart(ShowSplashWindow));
            //t.Start();
            //Thread.Sleep(500);
            //t.Abort();
            InitializeComponent();
        }

        private void ShowSplashWindow()
        {
            swin = new SplashWindow();
            swin.StartPosition = FormStartPosition.CenterScreen;
            swin.ShowDialog();
            swin.Dispose();
        }

        PGNode ViewdPGRoot = null;
        PGViewer viewer = null;
        Policy selectedPolicy = null;
        Microsoft.Glee.Drawing.Graph TempGraph = null;
        Node prevNode = null;
        
        
        private void listBox1_Click(object sender, EventArgs e)
        {
            MessageBox.Show(sender.ToString());
            MessageBox.Show(e.ToString());
            
            
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (((ListBox)sender).SelectedItem != null)
            {
                this.viewer = new PGViewer();
                IPropagationGraphReopository propagationGraphRepository = new PropagationGraphDBRepository();
                //if data stored in database:
                /*
                 * PGNode pgRoot = propagationGraphRepository.SelectGraph(((PGListItem)((ListBox)sender).SelectedItem).Value);
                */
                //if data stored in the memory:
                PGNode pgRoot = PGRepository[((PGListItem)((ListBox)sender).SelectedItem).Value];
                this.ViewdPGRoot = pgRoot;
                this.gViewer1.Graph = this.viewer.DrawGraph(pgRoot);
                this.AnalysisResultListBox.Items.Clear();
                propertyGrid1.SelectedObject = null;
            }
            
        }

        private void loadLogToolStripMenuItem_Click(object sender, EventArgs e)
        {           
            this.PGListBox.Items.Clear();
            this.AnalysisResultListBox.Items.Clear();

            propertyGrid1.SelectedObject = null;
            
            OpenFileDialog openFileDialog1 = new OpenFileDialog();           
            openFileDialog1.Filter = "XML files (*.xml)|*.xml";
            openFileDialog1.FilterIndex = 2;
            openFileDialog1.RestoreDirectory = true;            
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    LogEntryCollection logColl = new LogEntryCollection();
                    XMLParser xmlPrs = new XMLParser();
                    this.ProgressLabel.Text = "validating xml: " + DateTime.Now + "\n";
                    if (xmlPrs.ValidateXML(openFileDialog1.FileName))
                    {
                        this.ProgressLabel.Text += "validating xml done: " + DateTime.Now + "\n";
                        this.ProgressLabel.Text += "parsing xml: " + DateTime.Now + "\n";
                        logColl = xmlPrs.ParseLog(openFileDialog1.FileName);
                        this.ProgressLabel.Text += "parsing xml done: " + DateTime.Now + "\n";
                        PGConstructor pgCnstr = new PGConstructor();
                        List<string> GraphsHashValues = new List<string>();
                        //if the data stored in the database:
                        /*
                         * IPropagationGraphDBReopository propagationGraphRepository = new PropagationGraphDBRepository();
                         * this.ProgressLabel.Text += "clearing repo: " + DateTime.Now + "\n";
                         * propagationGraphRepository.ClearReposity();
                         * this.ProgressLabel.Text += "clearing repo done: " + DateTime.Now + "\n";
                        */
                        int graphNumber = 1;
                        progressBar1.Maximum = xmlPrs.workSize;
                        progressBar1.Value = 0;
                        foreach (ProcessLogEntry process in logColl.AllLogEntry.Values)
                        {
                            foreach (TraceLogEntry trace in process.Process.Values)
                            {
                                this.ProgressLabel.Text += "constructing: " + DateTime.Now + "\n";
                                PGNode fnode = pgCnstr.Construct(trace);
                                this.ProgressLabel.Text += "constructing done: " + DateTime.Now + "\n";
                                this.ProgressLabel.Text += "hashing: " + DateTime.Now + "\n";
                                string hashValue = PGHasher.GetHashValue(fnode, pgCnstr.AllNodes);
                                this.ProgressLabel.Text += "hashing done: " + DateTime.Now + "\n";
                                if (!GraphsHashValues.Contains(hashValue))
                                {
                                    GraphsHashValues.Add(hashValue);
                                    //if the data stored in the database:
                                    /*
                                    List<PGNode> nodeList = pgCnstr.AllNodes;
                                    this.ProgressLabel.Text += "storing in db: " + DateTime.Now + "\n";
                                    int pgid = propagationGraphRepository.Store(nodeList, fnode, hashValue);
                                    this.ProgressLabel.Text += "storing in db done: " + DateTime.Now + "\n";
                                    */
                                    //if the data is stored in the memory:
                                    PGRepository.Add(hashValue, fnode);
                                    this.PGListBox.Items.Add(new PGListItem { Text = "PG # " + graphNumber++, Value = hashValue });
                                }
                                progressBar1.Value++;
                                this.progressBar1.Refresh();
                                this.ProgressLabel.Refresh();
                            }
                        }
                        if (viewer != null)
                            this.gViewer1.Graph = this.viewer.Clear();
                    }
                    else
                    {
                        MessageBox.Show("Error: invalid xml file.");
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }
            }
        }

        private void AnalysisResultListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (((ListBox)sender).SelectedItem != null)
                this.gViewer1.Graph = this.viewer.ColorNodes(((ResultListItem)((ListBox)sender).SelectedItem).Value, Microsoft.Glee.Drawing.Color.Red);
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            Policy p = PolicyBuilder.GeneratePolicyForPaperRevision();
            PolicyListItem pli1 = new PolicyListItem { Text = p.Name, Value = p };

            Policy p2 = PolicyBuilder.GeneratePolicyForFlightReservation();
            PolicyListItem pli2 = new PolicyListItem { Text = p2.Name, Value = p2 };

            Policy p3 = PolicyBuilder.GenerateProductOrderPolicy();
            PolicyListItem pli3 = new PolicyListItem { Text = p3.Name, Value = p3 };

            Policy p4 = PolicyBuilder.GeneratePolicyForLoanRequest();            
            PolicyListItem pli4 = new PolicyListItem { Text = p4.Name, Value = p4 };
            this.PolicyListbox.Items.Add(pli1);
            this.PolicyListbox.Items.Add(pli2);
            this.PolicyListbox.Items.Add(pli3);
            this.PolicyListbox.Items.Add(pli4);
            
            gViewer1.MouseClick += new MouseEventHandler(gViewer1_MouseClick);
            //gViewer1.MouseHover += new EventHandler(gViewer1_MouseHover);
            
            
        }

        void gViewer1_MouseClick(object sender, MouseEventArgs e)
        {
            if (gViewer1.SelectedObject != null && gViewer1.SelectedObject.GetType().Name == "Node")
            {
                Node selectedNode = (Node)gViewer1.SelectedObject;

                if (prevNode != null)
                {
                    prevNode.Attr.Fillcolor = Microsoft.Glee.Drawing.Color.LightGreen;
                    gViewer1.Refresh();
                }

                string nname = selectedNode.Attr.Label;
                PGNode resultNode = viewer.DrawedNodes.Find(
                    delegate(PGNode n)
                    {
                        return n.Name == nname;
                    }
                );
                if (resultNode != null)
                {
                    propertyGrid1.SelectedObject = resultNode;                    
                    selectedNode.Attr.Fillcolor = Microsoft.Glee.Drawing.Color.Yellow;
                    prevNode = selectedNode;
                    gViewer1.Refresh();
                }
            }
            else
            {
                propertyGrid1.SelectedObject = null;
                if (prevNode != null)
                {
                    prevNode.Attr.Fillcolor = Microsoft.Glee.Drawing.Color.LightGreen;
                    gViewer1.Refresh();
                }
            }
        }

        
        private void PolicyListbox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (((ListBox)sender).SelectedItem != null)
                this.selectedPolicy = ((PolicyListItem)((ListBox)sender).SelectedItem).Value;
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }


        private void toolStripButton2_Click_1(object sender, EventArgs e)
        {
            propertyGrid1.SelectedObject = null;
            if (this.ViewdPGRoot == null)
            {
                MessageBox.Show("please select a pg");
                return;
            }
            if (selectedPolicy == null)
            {
                MessageBox.Show("please select a policy");
                return;
            }
            this.AnalysisResultListBox.Items.Clear();

            Analyzer analyzer = new Analyzer();
            List<PGNode> visitedNodes = new List<PGNode>();
            List<TriggeredRule> analysisResult = analyzer.analyze(this.ViewdPGRoot, selectedPolicy, visitedNodes);
            if (analysisResult.Count == 0)
                MessageBox.Show("No violation in the selected PG againsa this policy");
            foreach (TriggeredRule tr in analysisResult)
            {
                ResultListItem li = new ResultListItem();
                li.Text = tr.rule.ToText();
                li.Value = tr.path;
                this.AnalysisResultListBox.Items.Add(li);
            }            
        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {

        }

       
    }
}
